package springjunit;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.junit.Before;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.ComponentScan.Filter;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.FilterType;
import org.springframework.mock.web.MockHttpServletRequest;
import org.springframework.mock.web.MockHttpServletResponse;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.web.servlet.HandlerAdapter;
import org.springframework.web.servlet.HandlerMapping;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;

@RunWith(SpringJUnit4ClassRunner.class)
//@ContextConfiguration(loader = AnnotationConfigWebApplicationContextLoader.class)
@ContextConfiguration(locations = { "classpath:/spring/context-*.xml" })
public abstract class ControllerTestBase {

    @Autowired
    protected ApplicationContext context;

    protected MockHttpServletRequest request;
    protected MockHttpServletResponse response;
    protected HandlerAdapter ha;
    protected HandlerMapping mapping;

    @Autowired
    public void setContext(ApplicationContext context) {
        this.context = context;
    }

    @Configuration
    @EnableWebMvc
    @ComponentScan(basePackages = "your.application.packages.controller", excludeFilters = { @Filter(type = FilterType.ASSIGNABLE_TYPE, value = TestConfig.class) })
    static class TestConfig extends WebMvcConfigurerAdapter {
    }

    @Before
    public void setup() {
        request = new MockHttpServletRequest();
        request.setCharacterEncoding("UTF-8");

        response = new MockHttpServletResponse();
        response.setOutputStreamAccessAllowed(true);
        response.setCharacterEncoding("UTF-8");

        ha = context.getBean(RequestMappingHandlerAdapter.class);
        mapping = context.getBean(RequestMappingHandlerMapping.class);
    }

    public ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object controller) {
        try {
            return ha.handle(request, response, mapping.getHandler(request).getHandler());

        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
}